use actix_web::web::Data;
use sea_orm::{prelude::Expr, ColumnTrait, EntityTrait, QueryFilter};

use crate::{common::{error::ApiError, response::ApiResponse, types::ApiResult}, config::{auth::AuthInfo, state::AppState}, models::{entity::{prelude::{User, UserRole}, user, user_role}, request::auth_req::{DisableRequest, LoginRequest}, response::auth_res::LoginResponse}, utils::{password_util::PasswordUtil, redis_key::RedisKey, redis_util::RedisUtil}};



pub async fn login(state: Data<AppState>, param: LoginRequest) -> ApiResult<LoginResponse> {
    let user = User::find()
        .filter(user::Column::Deleted.eq(false))
        .filter(user::Column::Username.eq(param.username))
        .one(&state.db)
        .await?
        .ok_or(ApiError::BadRequest("用户名或密码错误"))?;

    match user.status {
        0 => (),
        _ => return Err(ApiError::Forbidden("用户已被禁用")),
    }

    if !PasswordUtil::verify_password(&param.password, &user.password)? {
        return Err(ApiError::BadRequest("用户名或密码错误"));
    }

    let user_role = UserRole::find()
        .filter(user_role::Column::Deleted.eq(false))
        .filter(user_role::Column::UserId.eq(user.id))
        .all(&state.db)
        .await?;

    let auth_user_key = RedisKey::auth_user_key(&user.id.to_string());
    let auth_user_str = RedisUtil::get(&state.redis, &auth_user_key)?;
    if let Some(token) = auth_user_str {
        let auth_token_key = RedisKey::auth_token_key(&token);
        RedisUtil::del(&state.redis, &auth_token_key)?;
        RedisUtil::del(&state.redis, &auth_user_key)?;
    }

    let auth_info = AuthInfo {
        user_id: user.id,
        role_ids: user_role.iter().map(|role| role.role_id).collect(),
    };

    let uuid = uuid::Uuid::new_v4().simple().to_string();
    let auth_token_key = RedisKey::auth_token_key(&uuid);
    let auth_token_str = serde_json::to_string(&auth_info)?;
    RedisUtil::set(&state.redis, &auth_token_key, &auth_token_str, 7200)?;
    RedisUtil::set(&state.redis, &auth_user_key, &uuid, 7200)?;

    let result = LoginResponse {
        user_id: user.id,
        nickname: user.nickname.clone(),
        token: uuid,
    };

    Ok(ApiResponse::ok(result))
}

pub async fn logout(state: Data<AppState>, auth_info: AuthInfo) -> ApiResult<bool> {
    let auth_user_key = RedisKey::auth_user_key(&auth_info.user_id.to_string());
    let auth_user_str = RedisUtil::get(&state.redis, &auth_user_key)?;
    if let Some(token) = auth_user_str {
        let auth_token_key = RedisKey::auth_token_key(&token);
        RedisUtil::del(&state.redis, &auth_token_key)?;
        RedisUtil::del(&state.redis, &auth_user_key)?;
    }
    Ok(ApiResponse::ok(true))
}

pub async fn disable(
    state: Data<AppState>,
    param: DisableRequest,
    _auth_info: AuthInfo,
) -> ApiResult<bool> {
    let user_ids = param.user_ids.clone();

    if user_ids.is_empty() {
        return Err(ApiError::BadRequest("用户ID不能为空"));
    }

    User::update_many()
        .col_expr(user::Column::Status, Expr::value(1))
        .filter(user::Column::Id.is_in(user_ids))
        .exec(&state.db)
        .await?;

    for id in param.user_ids {
        let auth_user_key = RedisKey::auth_user_key(&id.to_string());
        let auth_user_str = RedisUtil::get(&state.redis, &auth_user_key)?;
        if let Some(auth_token) = auth_user_str {
            let auth_token_key = RedisKey::auth_token_key(&auth_token);
            RedisUtil::del(&state.redis, &auth_user_key)?;
            RedisUtil::del(&state.redis, &auth_token_key)?;
        }
    }

    Ok(ApiResponse::ok(true))
}

pub async fn enable(
    state: Data<AppState>,
    param: DisableRequest,
    _auth_info: AuthInfo,
) -> ApiResult<bool> {
    let user_ids = param.user_ids;

    if user_ids.is_empty() {
        return Err(ApiError::BadRequest("用户ID不能为空"));
    }

    User::update_many()
        .col_expr(user::Column::Status, Expr::value(0))
        .filter(user::Column::Id.is_in(user_ids))
        .exec(&state.db)
        .await?;

    Ok(ApiResponse::ok(true))
}
